/** * Service Base contains all the network methods to fire middleware requests. * @module baseService * @requires jquery * @requires baseModel * @requires framework/js/constants/constants * @requires platform */ define([ 'jquery', 'baseModel', 'framework/js/constants/constants', 'platform' ], function ($, BaseModel, Constants, Platform) { 'use strict'; /** * Service Base contains all the network methods to fire middleware requests. * @class * @alias BaseService * @memberof module:baseService * @hideconstructor */ var BaseService = function () { /** * Assign this to self. * @member {Object} */ var self = this; /** * Creates a map of requests to handle repost. * @member {Object} */ var map = {}; /** * Creates a map of eTags per request URL. * @member {Object} */ var eTags = {}; /** * Holds the current active request count. * @member {Number} */ var counter = 0; /** * Array to hold the nonce values to be set for each middleware request. * @member {Array} */ var nonceKeys = []; /** * Instance of [BaseKOModel]{@linkcode BaseKOModel}. * @member {BaseKOModel} */ var baseModel = BaseModel.getInstance(); /** * Boolean to determine whether the request is a mock request. * @type {Boolean} */ var isMocked = false; /** * Stores the base URL of the middleware request, uses local JSON path if request is mocked.
* Uses [appBaseURL]{@linkcode Constants.appBaseURL} to determine middleware root URL. * @type {String} */ var baseUrl = isMocked ? '../json/' : Constants.appBaseURL; /** * Boolean to enable/disable nonce. * @type {Boolean} */ var nonceEnabled = true; /** * Stores success/failure for batch requests. * @type {Boolean} */ var batchSuccess = true; /** * Hold the platform properties. * @type {function} */ var platform; /** * Array of jQuery [Deferred]{@linkcode http://api.jquery.com/category/deferred-object/} to hold state of nonce request. * @type {Array.} */ var isNonceFetched = []; /** * A boolean which holds the state for current pending nonce. * @type {Boolean} */ var isNoncePending = false; /** * A boolean which holds the state for current pending authentication. * @type {Boolean} */ var isOn417 = false; var counterAjax = 0; /** * This function return the resource URL. * @function getResourceURL * @memberof BaseService * @inner * @param {String} url URL String * @param {String} [version] version of the application * @return {String} resource URL */ var getResourceURL = function (url, version) { var serverURL = platform('getServerURL'); if (serverURL) { return serverURL + baseUrl + '/' + (version || Constants.appDefaultVersion) + '/' + url; } return baseUrl + '/' + (version || Constants.appDefaultVersion) + '/' + url; }; /** * This function return the resource path. * @function getResourcePath * @memberof BaseService * @inner * @param {String} url URL String * @param {String} [version] version of the application * @return {String} resource path */ // getResourcePath = function (url, version) { // var serverURL = platform("getServerURL"); // if (serverURL) { // url = url.replace(serverURL + baseUrl, "").replace("/" + version + "/", "/"); // } // // if (url.includes('scb')) { // url = url.replace(baseUrl, "").replace("/scb", "").replace("/" + version + "/", "/"); // } // // return url.replace(baseUrl, "").replace("/" + version + "/", "/"); // }, var getResourcePath = function (url, version) { var serverURL = platform('getServerURL'); if (serverURL) { url = url.replace(serverURL + baseUrl, '').replace('/' + version + '/', ''); } if (url.includes('scb')) { url = url.replace(baseUrl, '').replace('/scb', '').replace('/' + version + '/', ''); } return url.replace(baseUrl, '').replace('/' + version + '/', ''); }; /** * This function strips out empty query parameters from the URL. * @function normalizeURL * @memberof BaseService * @inner * @param {String} url The URL to clean. * @return {String} Normalized URL is returned. */ var normalizeURL = function (url) { if (url.split('?').length > 1) { return url.split('?')[0] + '?' + url.split('?').pop().replace(/(&?)\w+=(?:&|undefined(&)?|null(&)?|$)/g, '$1').replace(/&$/, ''); } return url; }; /** * This function appends user-locale information to all outgoing network requests.
* Uses [add]{@linkcode BaseModel} method from QueryParams to append locale query parameter picked from current user locale from oj.Config.getLocale(). * @function addUserLocale * @memberof BaseService * @inner * @param {String} url The URL to which user-locale query parameter is to be added. * @return {String} Returns the URL with locale query parameter which holds user-locale code. */ var addUserLocale = function (url) { return baseModel.QueryParams.add(url, { locale: baseModel.getLocale() }); }; /** * The generic function which serves as completeHandler for all ajax requests. * @function genericCompleteHandler * @inner * @memberof BaseService * @param {jQuery.jqXHR} jqXHR The jqXHR object returned from jQuery [ajax]{@linkcode http://api.jquery.com/jquery.ajax/} call. * @param {String} textStatus The string categorizing the status of the request viz.
"success", "notmodified", "nocontent", "error", "timeout", "abort", or "parsererror"
* For more details, see [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings}. * @returns {void} */ var genericCompleteHandler = function (jqXHR, textStatus) { var eTag; if (this && this.type !== "GET") { delete map[this.type + this.url]; } batchSuccess = true; var key = JSON.parse(jqXHR.getResponseHeader("x-nonce")); if (key && key.hasOwnProperty("nonce")) { nonceKeys = nonceKeys.concat(JSON.parse(jqXHR.getResponseHeader("x-nonce")).nonce); nonceEnabled = true; } else { nonceEnabled = false; } if (this && this.url && this.type === "GET") { eTag = jqXHR.getResponseHeader("ETag"); if (eTag) { eTags[this.url] = eTag; } } Constants.currentServerDate.setTime(new Date(jqXHR.getResponseHeader("Date")).getTime()); /* if (jqXHR.status === 403) { var options = {}; options.url = "me"; options.type = "GET"; options.contentType = "application/json"; options.complete = function (jqXHR1) { if (jqXHR1.status === 401) { //location.reload(); } }; if (getResourceURL("me", this.version) !== this.url) { // Noncompliant@+1 {{Move the declaration of "fireAjax" before this usage.}} // eslint-disable-next-line no-use-before-define fireAjax(options, {}); } } if (jqXHR.getResponseHeader("BATCH_ID")) { for (var i = 0; i < jqXHR.responseJSON.batchDetailResponseDTOList.length; i++) { key = JSON.parse(jqXHR.responseJSON.batchDetailResponseDTOList[i].header["x-nonce"] || "{}"); if (key && key.hasOwnProperty("nonce")) { nonceKeys.push(key.nonce[0]); } if (jqXHR.responseJSON.batchDetailResponseDTOList[i].status >= 400) { batchSuccess = false; } } if (!batchSuccess) { baseModel.showMessages(jqXHR); } } else { if (this.showMessage && isOn417) { if (jqXHR.status === 400) { baseModel.showMessages(jqXHR, null, null, function () { location.reload(); isOn417 = false; }); } else { baseModel.showMessages(jqXHR); } } if (this.showMessage && !isOn417) { if (jqXHR.status === 409 || jqXHR.status === 403) { baseModel.showMessages(jqXHR, null, "ERROR", function () { location.reload(); }); //location.reload(); } else { baseModel.showMessages(jqXHR); } } if (textStatus === "timeout" && this.timeoutMessage) { baseModel.showMessages(null, [this.timeoutMessage], "ERROR"); } } if (jqXHR.status === 417) { jqXHR.abort(); counter--; this.url = getResourcePath(this.url, this.version); // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}} // eslint-disable-next-line no-use-before-define baseModel.showAuthScreen(jqXHR, this, (jqXHR.getResponseHeader("boundary") && jqXHR.getResponseHeader("boundary").indexOf("--OBDXbatch") > -1) ? fireBatchAjax : fireAjax, this.success); isOn417 = true; $('#button').removeAttr('disabled'); return false; } if (this && !this.selfLoader) { counter--; } if (counter === 0) { setTimeout(function () { if (counter === 0) { $(".se-pre-con").fadeOut("slow"); } }, 100); baseModel.lastUpdatedTime(new Date()); } if (jqXHR.status === 409) { window.location.search = ""; } else if (jqXHR.status === 403) { var options = {}; options.url = "me"; options.type = "GET"; options.contentType = "application/json"; options.complete = function (jqXHR1) { if (jqXHR1.status === 401) { window.location.search = ""; } }; if (getResourceURL("me", this.version) !== this.url) { // Noncompliant@+1 {{Move the declaration of "fireAjax" before this usage.}} // eslint-disable-next-line no-use-before-define fireAjax(options, {}); } } if (jqXHR.getResponseHeader('BATCH_ID')) { for (var i = 0; i < jqXHR.responseJSON.batchDetailResponseDTOList.length; i++) { key = JSON.parse(jqXHR.responseJSON.batchDetailResponseDTOList[i].header['x-nonce'] || '{}'); if (key && key.hasOwnProperty('nonce')) { nonceKeys.push(key.nonce[0]); } if (jqXHR.responseJSON.batchDetailResponseDTOList[i].status >= 400) { batchSuccess = false; } } if (!batchSuccess) { baseModel.showMessages(jqXHR); } } else { _processLoadingImage(false); // if (this.showMessage) { // if (isOn417) { // if (jqXHR.status === 400) { // baseModel.showMessages(jqXHR, null, null, function () { // // location.reload(); // isOn417 = false; // }); // } else { // baseModel.showMessages(jqXHR); // } // } else if (jqXHR.status === 409 || jqXHR.status === 403) { // baseModel.showMessages(jqXHR, null, 'ERROR', function () { // // index. se goi lai trang index. trong do se xoa session & cookie // window.onbeforeunload = null; // window.location = 'index.html?module=login'; // }); // } else { // baseModel.showMessages(jqXHR); // } // if (textStatus === 'timeout' && this.timeoutMessage) { // baseModel.showMessages(null, [this.timeoutMessage], 'ERROR'); // } // } if (this.showMessage) { baseModel.showMessages(jqXHR); } if (textStatus === "timeout" && this.timeoutMessage) { baseModel.showMessages(null, [this.timeoutMessage], "ERROR"); } } */ if (jqXHR.status === 417) { // jqXHR.abort(); // counter--; // this.url = getResourcePath(this.url, this.version); // // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}} // // eslint-disable-next-line no-use-before-define // baseModel.showAuthScreen(jqXHR, this, (jqXHR.getResponseHeader('boundary') && jqXHR.getResponseHeader('boundary').indexOf('--OBDXbatch') > -1) ? fireBatchAjax : fireAjax, this.success); // isOn417 = true; // $('#button').removeAttr('disabled'); // return false; // if (this.showMessage) { // baseModel.showMessages(jqXHR); // } counter--; // Dung 18/02/19 // Handle 417 with error : Vuot qua so lan xac thuc if ((jqXHR.responseJSON.status && jqXHR.responseJSON.status.message.code === 'DIGX_AUTH_0007') || (jqXHR.responseJSON.message && jqXHR.responseJSON.message.code === 'DIGX_AUTH_0007')) { baseModel.showMessages(jqXHR, null, null, function () { history.back(); window.onbeforeunload = null; }); } else { if (this.showMessage) { baseModel.showMessages(jqXHR); } // baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success); this.url = getResourcePath(this.url, this.version); // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}} // eslint-disable-next-line no-use-before-define // baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success); baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? self.uploadFile : fireAjax, this.success); // return false; } return false; // counter--; // this.url = getResourcePath(this.url, this.version); // // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}} // // eslint-disable-next-line no-use-before-define // baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success); // // baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? self.uploadFile : fireAjax, this.success); // return false; } if (this && !this.selfLoader) { counter--; } if (counter === 0) { setTimeout(function () { if (counter === 0) { $('.se-pre-con').fadeOut('slow'); } }, 100); baseModel.lastUpdatedTime(new Date()); } }; /** * Method to fetch nonce keys for base service. This method will fire a * POST request and based fetch nonce keys from the response header * and add them to [nonceKeys]{@linkcode BaseService~nonceKeys} array, from which a key is popped and added to each * going request. * @function getNonceForServiceInstance * @memberof BaseService * @instance * @param {Number} [nonceCount=15] The number of nonce requested. * @param {Number} [otp] The OTP for the current request. * @param {Number} [referenceNumber] Reference Number for the current request. * @returns {void} */ var getNonceForServiceInstance = function (nonceCount) { if ((nonceEnabled || nonceCount) && (nonceKeys.length < 5 || nonceCount) && !isNoncePending) { // console.log('--- lay nonce---:' + nonceCount + '---' + nonceKeys.length) isNoncePending = true; var options = {}; var currentNonce = $.Deferred(); options.type = 'POST'; // phucnnd them. Goi dong bo // options.async = false options.contentType = 'application/json'; options.showMessage = true; options.headers = { 'x-noncecount': nonceCount || 75 }; options.complete = function (jqXHR) { genericCompleteHandler.apply(this, [jqXHR]); currentNonce.resolve(); isNoncePending = false; // console.log('--- lay nonce xong---noncekey-nonceCount:' + nonceKeys + '--' + nonceCount) }; $('body').removeClass('loaded'); counter++; isNonceFetched.push(currentNonce); Platform.getInstance().then(function (instance) { platform = instance; options.url = getResourceURL('session/nonce'); platform('addHeader', options.headers); options.url = addUserLocale(options.url); options.url = normalizeURL(options.url); $.ajax(options); }); } }; /** * This object specifies the default ajax settings for all network calls fired via exported methods of [BaseService]{@linkcode BaseService}.
* See [list]{@linkcode module:baseService} of all such methods. * @type {Object} */ var defaults = { type: 'GET', url: '', async: true, contentType: 'application/json', headers: { 'X-Target-Unit': Constants.currentEntity, // phucnnd update. Cho giong voi ban mobile. Tuy nhien check login ban desktop lai 'X-Channel': Constants.channel }, dataType: 'json', showMessage: true, selfLoader: false, beforeSend: function (xhr) { getNonceForServiceInstance(); if (!this.selfLoader) { counter++; $('.se-pre-con').show(); } if (nonceKeys.length > 0) { var currentNonce = nonceKeys.pop(); xhr.setRequestHeader('x-nonce', currentNonce); } if (this.type !== 'GET' && !(this.headers.boundary && this.headers.boundary.indexOf('--OBDXbatch') > -1)) { if (!((this.type + this.url) in map)) { map[(this.type + this.url)] = this.type + this.url; } else { xhr.abort(); counter--; } if (this.url in eTags) { xhr.setRequestHeader('If-Match', eTags[this.url]); } } }, complete: genericCompleteHandler }; /** * This function utilizes [format]{@linkcode BaseModel#format} to parameterize URL. * Supports same arguments as [format]{@linkcode BaseModel#format}. See its documentation for more details. * @function parameterizeURL * @inner * @memberof BaseService */ var parameterizeURL = baseModel.format; /** * This function clears the [isNonceFetched]{@linkcode BaseService#isNonceFetched} array based on which deferreds are resolved. * @function clearIsNonceFetched * @inner * @memberof BaseService */ var clearIsNonceFetched = function () { isNonceFetched.forEach(function (deferred, index, array) { if (deferred.state() === 'resolved') { array.splice(index, 1); } }); }; /** * The main function which fires the actual ajax request.
* This function is called internally from all the exported methods of [BaseService]{@linkcode BaseService}. * Returns a promise which resolves/rejects with the network request. * @function fireAjax * @memberof BaseService * @inner * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @return {Promise} Returns the promise which resolves/rejects with the network request. */ var fireAjax = function (settings, params) { //_processLoadingImage(true); if (settings.nonceRequired) { nonceEnabled = true; } var language = sessionStorage.getItem('user-locale') || document.getElementsByTagName('html')[0].getAttribute('lang') || 'en'; // nonceEnabled = true; getNonceForServiceInstance(); return new Promise(function (resolve, reject) { Promise.all(isNonceFetched).then(function () { clearIsNonceFetched(); defaults.headers['X-Target-Unit'] = Constants.currentEntity; var options = $.extend(true, {}, defaults, settings); options.version = options.version || Constants.appDefaultVersion; // customize if (!options.externalURL) { options.url = getResourceURL(options.url, options.version); } if (params) { options.url = parameterizeURL(options.url, params, true); } if (settings.versionApp) { options.url = 'https://ebanking.scb.com.vn/index/json/version.json'; } options.promiseResolve = resolve; if (options.url.includes('/batch') === true && options.headers.TOKEN_ID !== null) { // console.log('url.includes(/batch)===true'); // return baseUrl + url; options.url = "/digx/batch"; } options.url = addUserLocale(options.url); options.url = normalizeURL(options.url); // console.log('---service base--:' + options.url) if (settings.isCustomize) { // options.url = self.baseUrlCz + (self.isMocked ? options.url.split('?')[0] : options.url); options.url = options.url.replace('/digx', '/digx/scb'); } else { if (settings.isTest) { options.url = options.url.includes(self.baseUrlCzTest) ? (self.isMocked ? options.url.split('?')[0] : options.url) : self.baseUrlCzTest + (self.isMocked ? options.url.split('?')[0] : options.url); } else if (settings.isURLthach) { if (options.url.includes(self.baseUrlCzThach)) { options.url = options.url.replace(self.baseUrlCzThach, ''); } options.url = self.baseUrlCzThach + (self.isMocked ? options.url.split('?')[0] : options.url); } else if (settings.isURLcz1) { options.url = options.url.replace("/digx/v1", "/digx/cz/v1"); //self.baseUrlCz_1; //options.url.replace(options.url, } else if (settings.isMode) { options.url = options.url.replace("/digx/v1", "/digx/v1/scb"); } } // phucnnd them tu compare Oracle platform('addHeader', options.headers); // console.log('----options.url:' + options.url); // console.log('----options.headers:' + options.headers); // phucnnd them // options.async = false // 60 giay // co the gay response tra ve canceled // options.timeout = 300000; // var error = options.error; var success = options.success; options.success = function (jqXHR, textStatus, data) { _processLoadingImage(false); resolve(data, textStatus, jqXHR); if (success) { success(jqXHR, textStatus, data); } }; // options.error = function (jqXHR, textStatus, data) { // // _processLoadingImage(false); // resolve(jqXHR, textStatus, data); // // if (success) { // // error(jqXHR, textStatus, data); // // } // }; $.ajax(options).done(function (data, textStatus, jqXHR) { _processLoadingImage(false); // console.log('---service base--success resolve'); Constants.currentEntity = jqXHR.getResponseHeader("X-Target-Unit"); resolve(data, textStatus, jqXHR); }).fail(function (jqXHR, textStatus, errorThrown) { // data console.log('----jqXHR fail-textStatus-data' + jqXHR + textStatus + errorThrown); _processLoadingImage(false); if (jqXHR && jqXHR.status === 400 && jqXHR.readyState === 4) { // {"result":"SUCCESSFUL","contextID":"005Umf5taHk4YrWjLxJN8A000VQK002xpI,0:1","message":{"title":"Yêu cầu thay đổi mật khẩu.","detail":"Yêu cầu thay đổi mật khẩu.","code":"DIGX_UM_042","type":"ERROR"}} // II Dung remove show message // Tìm những trường hợp bị lỗi ko có message từ service để show lên // DIGX_DDA_049 for get DORMANT account if (jqXHR.responseJSON !== null && jqXHR.responseJSON.message !== null && jqXHR.responseJSON.message.code === "DIGX_DDA_049") { // Force change password _processLoadingImage(false); resolve(errorThrown, textStatus, jqXHR); if (success) { success(jqXHR, textStatus, errorThrown); } // Trường hợp là force change password return true; } else { // Error : Yeu cau thay doi mat khau if (jqXHR.responseJSON.message.code === "DIGX_UM_042") { reject(jqXHR, textStatus, errorThrown); baseModel.showMessages(null, [jqXHR.responseJSON.message.detail], 'INFO'); //baseModel.checkAndShowError(jqXHR); // Error : Loi ko xac dinh : unexpected } else if (jqXHR.responseJSON.message.code === "DIGX_AUTH_0003") { reject(jqXHR, textStatus, errorThrown); } else if (jqXHR.responseJSON.message.code === "3403") { baseModel.showMessages(null, ['Có lỗi xảy ra - Xin vui lòng thử lại'], null, function () { history.back(); window.onbeforeunload = null; }); // Error when No transaction } else { baseModel.checkAndShowError(jqXHR); } // else if (jqXHR.responseJSON.message.code === "DIGX_DDA_007" // || jqXHR.responseJSON.message.code === "DIGX_OR_TD_0012" // || jqXHR.responseJSON.message.code === "DIGX_LA_0007" // // Dung cho loi khong lay duoc data cua nhat ki giao dich Maker & Checker // || jqXHR.responseJSON.message.code === "DIGX_AP_0039") { // baseModel.showMessages(jqXHR); // } else { // baseModel.showMessages(jqXHR, null, null, function () { // history.back(); // window.onbeforeunload = null; // }); // } return false; } } else if (jqXHR.status === 403) { // check lai coi phai loi het session khong. if (jqXHR.responseJSON.message.code === 'DIGX_PROD_ACCESS_DENIED_0000') { baseModel.showMessages(jqXHR, null, 'ERROR', function () { // index. se goi lai trang index. trong do se xoa session & cookie window.onbeforeunload = null; window.location = 'index.html?module=login'; }); } else { reject(jqXHR, textStatus, errorThrown); } return false; } else if (jqXHR.status === 409) { reject(jqXHR, textStatus, errorThrown); var _lang = null; if (language === 'vn') { _lang = 'Phiên giao dịch của bạn đã hết hiệu lực. Vui lòng đăng nhập lại để tiếp tục.'; } else { _lang = 'Session is expired. Please login again'; } baseModel.showMessages(null, [_lang], 'ERROR', function () { // index. se goi lai trang index. trong do se xoa session & cookie window.onbeforeunload = null; window.location = 'index.html?module=login'; }); } else if (jqXHR.status === 503) { reject(jqXHR, textStatus, errorThrown); console.log('---service base--503---ko chay reject'); return false; } else if (jqXHR.status === 0) { if (jqXHR.statusText === 'canceled') { _processLoadingImage(false); return true; } reject(jqXHR, textStatus, errorThrown); var _lang = null; if (language === 'vn') { _lang = 'Có lỗi xảy ra - Vui lòng thử lại trong ít phút'; } else { _lang = 'An error occurred - Please try again in a few minutes'; } baseModel.showMessages(null, [_lang], 'ERROR', function () { // index. se goi lai trang index. trong do se xoa session & cookie history.back(); window.onbeforeunload = null; }); Constants.currentEntity = jqXHR.getResponseHeader("X-Target-Unit"); // return false; } else if (jqXHR.status !== 417) { reject(jqXHR, textStatus, errorThrown); console.log('---service base--!417---ko chay reject'); return false; } }); // //PHUC commment _processLoadingImage(true); // Promise.resolve($.ajax(options)).then(resolve, reject); }); }); }; var _processLoadingImage = function (isstart) { if (isstart === true) { counterAjax++; // console.log('counterAjax start++: ' + counterAjax); if (counterAjax > 0) { $('#divOverlay').show(); // var timer = setTimeout(function () { $('#divOverlay').show(); }, 2000); // clearTimeout(timer); } } else { counterAjax--; // console.log('counterAjax stop--: ' + counterAjax); if (counterAjax <= 0) { counterAjax = 0; $('#divOverlay').hide(); } } }; /** * The main function which fires the actual batch ajax request.
* This function is called internally from [batch]{@linkcode BaseService#batch}. * @function fireBatchAjax * @memberof BaseService * @inner * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {void} */ var fireBatchAjax = function (settings) { var matches = settings.data.match(/x-nonce:\s(.*?)\r\n/g); getNonceForServiceInstance((nonceKeys.length - matches.length) < 0 && Math.abs(nonceKeys.length - matches.length)); Promise.all(isNonceFetched).then(function () { clearIsNonceFetched(); matches.forEach(function (oldNonceHeader) { settings.data = settings.data.replace(oldNonceHeader, "x-nonce: " + nonceKeys.pop() + "\r\n"); }); var options = $.extend(true, {}, defaults, settings); var serverURL = platform("getServerURL"); if (serverURL) { options.url = serverURL + baseUrl + "/batch"; } else { options.url = baseUrl + "/batch"; } options.url = addUserLocale(options.url); platform("addHeader", options.headers); $.ajax(options).fail(function (jqXHR, textStatus, errorThrown) { if (jqXHR.status === 417) { if (jqXHR.responseJSON.message.code === 'DIGX_AUTH_0007') { baseModel.showMessages(jqXHR, null, null, function () { history.back(); window.onbeforeunload = null; }); } else { baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success); } return false; } else { baseModel.showMessages(jqXHR, null, null, function () { history.back(); window.onbeforeunload = null; }); return false; } }); }); }, /** * Generates a random string using Math for use by [batch]{@linkcode BaseService#batch}. * @function generateRandomString * @inner * @memberof BaseService * @param {Number} length The length of string desired * @return {String} Random string of desired length is returned. */ generateRandomString = (function (length) { return function () { return Math.round((Math.pow(36, length + 1) - (Math.random() * Math.pow(36, length)))).toString(36).slice(1); }; })(10), /** * Create payload for batch request. * @function buildBatchRequest * @memberof BaseService * @inner * @param {Object} data The non-formatted payload parameter sent to buildBatchRequest for formatting. * @param {String} boundary The boundary string for separating individual requests of batch request. * @return {Object} The payload object to be fired is returned. */ buildBatchRequest = function (data, boundary) { var payload = ""; var batchPayloadFormat = { boundary: "--{boundary}\r\n", header: "{key}: {value}\r\n", url: "\r\n{methodType} {url} HTTP/{majorminorversion}\r\n", payload: "\r\n{payload}\r\n", end: "--{boundary}--\r\n" }; for (var i = 0; i < data.batchDetailRequestList.length; i++) { payload += baseModel.format(batchPayloadFormat.boundary, { boundary: boundary }); payload += baseModel.format(batchPayloadFormat.header, { key: "x-nonce", value: "nonce" }); for (var key in data.batchDetailRequestList[i].headers) { if (data.batchDetailRequestList[i].headers.hasOwnProperty(key)) { payload += baseModel.format(batchPayloadFormat.header, { key: key, value: data.batchDetailRequestList[i].headers[key] }); } } payload += baseModel.format(batchPayloadFormat.url, { methodType: data.batchDetailRequestList[i].methodType, url: addUserLocale(parameterizeURL(data.batchDetailRequestList[i].uri.value, data.batchDetailRequestList[i].uri.params, true)), majorminorversion: "1.1" }); if (data.batchDetailRequestList[i].payload && data.batchDetailRequestList[i].payload.trim()) payload += (baseModel.format(batchPayloadFormat.payload, { payload: data.batchDetailRequestList[i].payload.trim() })); } return payload += (baseModel.format(batchPayloadFormat.end, { boundary: boundary })); }; self.baseUrl = (self.isMocked ? '../json/' : window.APPLICATION_BASE_URL); self.baseUrlCz = (self.isMocked ? '../json/' : window.APPLICATION_BASE_URL_CZ); self.isMocked = false; /** * Utility function to parse special characters from received response. * @inner * @function characterEncoding * @memberof BaseService * @param {Object} obj The object received from response containing special characters. * @return {Object} The parsed object is returned. */ function characterEncoding(obj) { for (var property in obj) { if (obj.hasOwnProperty(property)) { if (typeof obj[property] === 'object') { characterEncoding(obj[property]); } else if (typeof obj[property] === 'string' && obj[property] !== '') { obj[property] = $('
').html(obj[property]).text(); } } } return obj; } /** * Download a file. * @function downloadFile * @instance * @memberof BaseService * @param {Object} options The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {void} * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/loan/{accountId}/schedule?media=application/pdf&fromDate={fromDate}&toDate={toDate}' * }; * var params = { 'accountId': accountId, 'fromDate': fromDate, 'toDate': toDate }; * baseService.downloadFile(options, params); */ self.downloadFile = function (options, params) { $('.se-pre-con').show(); options.url = getResourceURL(options.url, options.version); if (params) { options.url = parameterizeURL(options.url, params, true); } options.url = addUserLocale(options.url); options.url = normalizeURL(options.url); if (options.isCustomize) { options.url = options.url.replace('/digx', '/digx/scb'); } else { if (options.isRoot) { options.url = options.url.replace('/digx/v1', ''); } } getNonceForServiceInstance(); platform('downloadFile', options, nonceKeys.pop(), genericCompleteHandler); }; /** * Fires a POST request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}. * @function add * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/deposit/{accountId}/penalities', * data: postDataToBeSent * }; * var params = { 'accountId': accountId }; * return baseService.add(options, params); */ self.add = function (settings, params) { if (!isMocked) { settings.type = 'POST'; return fireAjax(settings, params); } }; /** * Fires a batch request for passed parameters. Delegates the ajax call to [fireBatchAjax]{@linkcode BaseService~fireBatchAjax}. * @function batch * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @param {Object} data The non-formatted payload parameter sent to buildBatchRequest for formatting. * @returns {void} * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'batch' * }; * baseService.batch(options, {}, batchRequestData); */ self.batch = function (settings, params, data) { var boundary = "--OBDXbatch" + generateRandomString(); settings.type = "POST"; settings.contentType = "multipart/mixed"; if (settings.headers) { settings.headers["boundary"] = boundary; settings.headers["X-BATCH_TYPE"] = params.type; settings.headers["X-Target-Unit"] = Constants.currentEntity; } else { settings.headers = { "boundary": boundary, "X-BATCH_TYPE": params.type, "X-Target-Unit": Constants.currentEntity }; } settings.requestType = "batch"; settings.data = buildBatchRequest(data, boundary); var successHandler = settings.success; settings.success = function (data, status, jqXHR) { for (var i = 0; i < data.batchDetailResponseDTOList.length; i++) { data.batchDetailResponseDTOList[i].responseObj = characterEncoding(JSON.parse(data.batchDetailResponseDTOList[i].responseText)); } if (successHandler) { successHandler(data, status, jqXHR); } }; fireBatchAjax(settings, params); }; /** * Fires an PUT request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}. * @function update * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/deposit/{accountId}/penalities', * data: updateData * }; * var params = { 'accountId': accountId }; * return baseService.update(options, params); */ self.update = function (settings, params) { if (!isMocked) { settings.type = 'PUT'; return fireAjax(settings, params); } }; /** * Fires a PATCH request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}. * @function patch * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/deposit/{accountId}/penalities' * }; * var params = { 'accountId': accountId }; * return baseService.patch(options, params); */ self.patch = function (settings, params) { if (!isMocked) { settings.type = 'PATCH'; return fireAjax(settings, params); } }; /** * Fires a DELETE request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}. * @function remove * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/deposit/{accountId}/penalities' * }; * var params = { 'accountId': accountId }; * return baseService.remove(options, params); */ self.remove = function (settings, params) { if (!isMocked) { settings.type = 'DELETE'; settings.dataFilter = function (data) { // console.log('---remove : data' + data); if (!data) { return '{}'; } return data; }; // console.log('---' + settings.url); return fireAjax(settings, params); } }; /** * Fires a GET request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}. * @function fetch * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'accounts/deposit/{accountId}/penalities' * }; * var params = { 'accountId': accountId }; * return baseService.fetch(options, params); */ self.fetch = function (settings, params) { settings.type = 'GET'; var successHandler = settings.success; settings.success = function (data, status, jqXHR) { data = characterEncoding(data); if (successHandler) { successHandler(data, status, jqXHR); } }; return fireAjax(settings, params); }; /** * Fetches a JSON. Uses json plugin of RequireJS to fetch the JSON. * @function fetchJSON * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {Promise} Returns the promise which resolves or reject when request succeeds or fails respectively. * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'dashboard/{moduleName}' * }; * var params = { 'moduleName': moduleName }; * return baseService.fetchJSON(options, params); */ self.fetchJSON = function (settings, params) { settings.url = parameterizeURL(settings.url, params, true); return new Promise(function (resolve) { require(['json!' + settings.url], function (json) { resolve(json); if (settings.success) settings.success(json); }); }); }; // /** // * Store Account information // */ self.storeAccount = function () { var deferred = $.Deferred(); var options = { url: "scb/accounts?status=ACTIVE&status=DORMANT", success: function (data) { deferred.resolve(data); }, error: function (data) { deferred.reject(data); } }; if (baseModel.cordovaDevice()) { window.plugins.appPreferences.fetch('accountData').then((data) => { if (!data) { self.fetch(options); deferred.done(function (d) { window.plugins.appPreferences.store('accountData', d); }).fail(function (e) { console.log(e); }); } }); } else if (typeof (Storage) !== "undefined") { if (!window.sessionStorage.getItem('accountData')) { self.fetch(options); deferred.done(function (d) { window.sessionStorage.setItem('accountData', JSON.stringify(d)); }).fail(function (e) { console.log(e); }); } } else { // Browser not support Stograge yet console.log('Browser not support Stograge yet.'); } }; // /** // * Get Account storage // */ // self.getAccountStorage = function (callback) { // if (baseModel.cordovaDevice()) { // window.plugins.appPreferences.fetch('accountData').then((data) => { // callback(data); // }); // } else if (typeof (Storage) !== "undefined") { // callback(JSON.parse(window.sessionStorage.getItem('accountData'))); // } // }; // /** // * Update Account balance // */ // self.updateAccountBalance = function (accNum) { // self.getAccountStorage(function (data) { // // for(let i in data.accounts){ // // let d = data.accounts[i]; // // if(accNum === d.id.value){ // // d.availableBalance = amount; // // break; // // } // // } // // calling rest // var deferred = $.Deferred(); // var options = { // params: {}, // url: "accounts/demandDeposit/{accNum}", // success: function (data) { // deferred.resolve(data); // }, // error: function (data) { // deferred.reject(data); // } // }; // var params = { 'accNum': accNum }; // self.fetch(options, params); // deferred.done(function (newData) { // for (var i in data.accounts) { // var d = data.accounts[i]; // console.log(newData) // console.log('--------------') // if (newData.demandDepositAccountDTO.id.value === d.id.value) { // console.log('before updating'); // console.log(d); // d.availableBalance = newData.demandDepositAccountDTO.availableBalance; // d.currentBalance = newdata.demandDepositAccountDTO.currentBalance; // d.productDTO = newdata.demandDepositAccountDTO.productDTO; // d.status = newdata.demandDepositAccountDTO.status; // console.log('updated: '); // console.log(d); // break; // } // } // }).fail(function () { // console.log('Calling rest to update accountData failture.'); // }); // }); // } /** * Uploads a file to the server. * @function uploadFile * @memberof BaseService * @instance * @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details. * @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}. * @returns {void} * @example * var baseService = BaseService.getInstance(); * var options = { * url: 'brand/{brandId}', * formData: form, * type: 'PUT' * }; * var params = { 'brandId': brandId }; * baseService.uploadFile(options, params); */ self.uploadFile = function (settings, params) { settings.type = "POST"; if (!isMocked) { var xhr = new XMLHttpRequest(), response, // Extend the settings object // var options = $.extend({}, defaults, settings); options = $.extend(true, {}, defaults, settings); //Appending the url with the context options.url = getResourceURL(options.url, options.version); if (params) { options.url = parameterizeURL(options.url, params, true); } options.url = addUserLocale(options.url); options.url = normalizeURL(options.url); options.requestType = "upload"; // readying xhr for nonce xhr.open(settings.type || 'POST', options.url, true); xhr.responseType = 'json'; /* options.beforeSend(xhr); xhr.onreadystatechange = function () { if (this.readyState === 4) { if (typeof this.response === 'string') { response = JSON.parse(this.response); } else { response = this.response; } if (options.success && (this.status === 200 || this.status === 201)) { options.success(response, this.status, this); } else if (options.error) { options.error(response, this.status, this); } this.responseJSON = response; genericCompleteHandler.apply(options, [xhr]); } }; xhr.send(options.formData); */ options.beforeSend(xhr); Object.keys(options.headers).forEach(function (key) { xhr.setRequestHeader([key], options.headers[key]); }); xhr.send(options.formData); return new Promise(function (resolve, reject) { xhr.onreadystatechange = function () { if (this.readyState === 4) { if (typeof this.response === "string") { response = JSON.parse(this.response); } else { response = this.response; } if (this.status === 200) { resolve(); } else if (this.status !== 417) { reject(); } if (options.success && (this.status === 200 || this.status === 201)) { options.success(response, this.status, this); } else if (options.error && this.status !== 417) { options.error(response, this.status, this); } this.responseJSON = response; genericCompleteHandler.apply(options, [xhr]); baseModel.checkAndShowError(this); } }; }); } }; /* Lay danh detail payment de lay duyet cua Doanh Nghiep */ var getTransferDataDeferred; var getTransferData = function (paymentId, deferred) { // var getTransferDataDeferred = $.Deferred(); // &getAuthType=Y //&getFee=Y var url = 'payment/inquiry/' + paymentId + '?status=init&getAuthType=Y&getFee=Y'; var options = { url: url, isCustomize: true, success: function (data) { deferred.resolve(data); }, error: function (data) { deferred.reject(data); } }; self.fetch(options); }; self.getDetailPaymentID = function (myself) { var paymentId = null; if (myself.params.transferData && myself.params.transferData.instructionId) { paymentId = myself.params.transferData.instructionId; } else if (myself.params.transferData && myself.params.transferData.paymentId) { paymentId = myself.params.transferData.paymentId; } else if (myself.params.data) { paymentId = myself.params.data.paymentId || myself.params.data.instructionId; } else { return $.Deferred(); } // if (!paymentId || paymentId()) { // return null; // } getTransferDataDeferred = $.Deferred(); getTransferData(paymentId(), getTransferDataDeferred); return getTransferDataDeferred; // getTransferData(paymentId).done(function (data) { // selfPaymentData = data; // }).then(function () { // return selfPaymentData; // }); }; /* self.getNonce = function () { var nonce; getNonceForServiceInstance(); if (nonceKeys.length > 0) { nonce = nonceKeys.pop(); counter++; } return nonce; }; */ /* */ self.initLabel = function () { var ids = document.querySelectorAll('[id$="_LABEL"]'); ids.forEach(item => { var id_tmp = item.id; if (!$('#' + id_tmp.replace("_LABEL", ''))[0]) { console.log(" id_tmp not value : " + id_tmp); } // || $('#' + id_tmp.replace("_LABEL", ''))[0].innerText !== '' if ($('#' + id_tmp.replace("_LABEL", ''))[0] && ($('#' + id_tmp.replace("_LABEL", ''))[0].value.length != "" || ($('#' + id_tmp.replace("_LABEL", ''))[0].type === "select-one" && $('#' + id_tmp.replace("_LABEL", ''))[0].parentNode.innerText != ""))) { $('#' + item.id).addClass('active'); } }); }; }; /** * Holds the instance of [BaseService]{@linkcode BaseService} * @memberof module:baseService * @inner * @type {BaseService} */ var instance; /** * Creates a instance of service base and returns it. * @function createInstance * @memberof module:baseService * @inner * @return {BaseService} Instance of service base. */ function createInstance() { var baseService = new BaseService(); /** * The exported methods of base service. * @type {Object} * @name ServiceBaseExports * @instance * @property {Function} add - Fires a POST request. See [add]{@linkcode BaseService#add} for detailed usage and documentation. * @property {Function} patch - Fires a PATCH request. See [patch]{@linkcode BaseService#patch} for detailed usage and documentation. * @property {Function} fetch - Fires a GET request. See [fetch]{@linkcode BaseService#fetch} for detailed usage and documentation. * @property {Function} update - Fires an PUT request. See [update]{@linkcode BaseService#update} for detailed usage and documentation. * @property {Function} remove - Fires a DELETE request. See [remove]{@linkcode BaseService#remove} for detailed usage and documentation. * @property {Function} batch - Fires a batch request. See [batch]{@linkcode BaseService#batch} for detailed usage and documentation. * @property {Function} fetchJSON - Fetches a local JSON. See [fetchJSON]{@linkcode BaseService#fetchJSON} for detailed usage and documentation. * @property {Function} downloadFile - Download a file. See [downloadFile]{@linkcode BaseService#downloadFile} for detailed usage and documentation. * @property {Function} uploadFile - Upload a file. See [uploadFile]{@linkcode BaseService#uploadFile} for detailed usage and documentation. */ var ServiceBaseExports = { add: baseService.add, patch: baseService.patch, fetch: baseService.fetch, update: baseService.update, remove: baseService.remove, batch: baseService.batch, fetchJSON: baseService.fetchJSON, downloadFile: baseService.downloadFile, uploadFile: baseService.uploadFile, getDetailPaymentID: baseService.getDetailPaymentID, storeAccount: baseService.storeAccount, initLabel: baseService.initLabel }; /*, getNonce: baseService.getNonce */ // // storeAccount: baseService.storeAccount, // getAccountStorage: baseService.getAccountStorage, // updateAccountBalance: baseService.updateAccountBalance return ServiceBaseExports; } return { /** * Get the Service Base instance. Checks [instance]{@linkcode module:baseService~instance} for instance. If exists, returns it, else invokes [createInstance]{@linkcode module:baseService~createInstance} to create an instance and returns it. * @function getInstance * @memberof module:baseService * @static * @returns {BaseService} The base service instance. */ getInstance: function () { if (!instance) { instance = createInstance(); } return instance; } }; });